import 'package:dartkit/dartkit.dart';
import 'package:test/test.dart';

void main() {
  test('构建时开始不能>=结束', () {
    DateTime begin = DateTime(2024, 1, 1, 12, 0, 0);
    DateTime end = DateTime(2024, 1, 1, 11, 59, 59);

    expect(() => Period(begin, end), isBug);

    end = DateTime(2024, 1, 1, 12, 0, 0);
    expect(() => Period(begin, end), isBug);
  });

  test('使用同样的数据构建的period，是同一个东西', () {
    DateTime begin = DateTime(2024, 1, 1, 12, 0, 0);
    DateTime end = DateTime(2024, 1, 1, 12, 30, 0);

    Period period1 = Period(begin, end);
    Period period2 = Period(begin, end);

    expect(period1, equals(period2));
    expect(period1.hashCode, equals(period2.hashCode));
  });

  group('时间段交集测试', () {
    test('具有交集的时间段', () {
      var p1 = Period(DateTime(2023, 1, 1), DateTime(2023, 1, 10));
      var p2 = Period(DateTime(2023, 1, 5), DateTime(2023, 1, 15));
      var intersection = p1.intersect(p2);
      expect(intersection, isNotNull);
      expect(intersection!.begin, DateTime(2023, 1, 5));
      expect(intersection.end, DateTime(2023, 1, 10));
    });

    test('没有交集的时间段', () {
      var p1 = Period(DateTime(2023, 1, 1), DateTime(2023, 1, 5));
      var p2 = Period(DateTime(2023, 1, 6), DateTime(2023, 1, 10));
      var intersection = p1.intersect(p2);
      expect(intersection, isNull);
    });

    test('完全相同的时间段', () {
      var p1 = Period(DateTime(2023, 1, 1), DateTime(2023, 1, 10));
      var p2 = Period(DateTime(2023, 1, 1), DateTime(2023, 1, 10));
      var intersection = p1.intersect(p2);
      expect(intersection, isNotNull);
      expect(intersection!.begin, DateTime(2023, 1, 1));
      expect(intersection.end, DateTime(2023, 1, 10));
    });

    test('一个时间段完全包含另一个时间段', () {
      var p1 = Period(DateTime(2023, 1, 1), DateTime(2023, 1, 15));
      var p2 = Period(DateTime(2023, 1, 5), DateTime(2023, 1, 10));
      var intersection = p1.intersect(p2);
      expect(intersection, isNotNull);
      expect(intersection!.begin, DateTime(2023, 1, 5));
      expect(intersection.end, DateTime(2023, 1, 10));
    });
  });

  group('时间段列表交集测试', () {
    test('列表中的时间段与给定时间段有交集', () {
      var periods = [
        Period(DateTime(2023, 1, 1), DateTime(2023, 1, 10)),
        Period(DateTime(2023, 1, 5), DateTime(2023, 1, 15)),
        Period(DateTime(2023, 1, 20), DateTime(2023, 1, 25))
      ];
      var intersectPeriod = Period(DateTime(2023, 1, 7), DateTime(2023, 1, 22));

      var intersections = periods.intersect(intersectPeriod);

      expect(intersections.length, 3);
      expect(intersections[0].begin, DateTime(2023, 1, 7));
      expect(intersections[0].end, DateTime(2023, 1, 10));
      expect(intersections[1].begin, DateTime(2023, 1, 7));
      expect(intersections[1].end, DateTime(2023, 1, 15));
      expect(intersections[2].begin, DateTime(2023, 1, 20));
      expect(intersections[2].end, DateTime(2023, 1, 22));
    });

    test('列表中的时间段与给定时间段无交集', () {
      var periods = [
        Period(DateTime(2023, 1, 1), DateTime(2023, 1, 5)),
        Period(DateTime(2023, 1, 20), DateTime(2023, 1, 25))
      ];
      var intersectPeriod =
          Period(DateTime(2023, 1, 10), DateTime(2023, 1, 15));

      var intersections = periods.intersect(intersectPeriod);

      expect(intersections.isEmpty, true);
    });

    test('列表为空时', () {
      var periods = <Period>[];
      var intersectPeriod =
          Period(DateTime(2023, 1, 10), DateTime(2023, 1, 15));

      var intersections = periods.intersect(intersectPeriod);

      expect(intersections.isEmpty, true);
    });
  });

  group('自定义日周期测试', () {
    test('当前时间在分界线之前', () {
      // 假设分界线是上午9点（09:00）
      int boundaryHour = 9;

      // 当前时间是上午8点（08:00）
      DateTime currentTime = DateTime(2023, 1, 1, 8, 0);

      // 计算自定义日周期
      Period period = getTimePeriod(currentTime, boundaryHour);

      // 预期的开始时间是前一天的上午9点
      DateTime expectedStart = DateTime(2022, 12, 31, 9, 0);
      // 预期的结束时间是当天的上午9点
      DateTime expectedEnd = DateTime(2023, 1, 1, 9, 0);

      expect(period.begin, expectedStart);
      expect(period.end, expectedEnd);
    });

    test('当前时间在分界线之后', () {
      // 假设分界线是上午9点（09:00）
      int boundaryHour = 9;

      // 当前时间是上午10点（10:00）
      DateTime currentTime = DateTime(2023, 1, 1, 10, 0);

      // 计算自定义日周期
      Period period = getTimePeriod(currentTime, boundaryHour);

      // 预期的开始时间是当天的上午9点
      DateTime expectedStart = DateTime(2023, 1, 1, 9, 0);
      // 预期的结束时间是第二天的上午9点
      DateTime expectedEnd = DateTime(2023, 1, 2, 9, 0);

      expect(period.begin, expectedStart);
      expect(period.end, expectedEnd);
    });

    test('当前时间正好是分界线时间', () {
      // 假设分界线是上午9点（09:00）
      int boundaryHour = 9;

      // 当前时间是上午9点（09:00）
      DateTime currentTime = DateTime(2023, 1, 1, 9, 0);

      // 计算自定义日周期
      Period period = getTimePeriod(currentTime, boundaryHour);

      // 预期的开始时间是当天的上午9点
      DateTime expectedStart = DateTime(2023, 1, 1, 9, 0);
      // 预期的结束时间是第二天的上午9点
      DateTime expectedEnd = DateTime(2023, 1, 2, 9, 0);

      expect(period.begin, expectedStart);
      expect(period.end, expectedEnd);
    });
  });

  group('按日交集计算测试', () {
    test('获取指定日期的时间段交集', () {
      // 创建包含多个时间段的列表
      var periods = [
        Period(
            DateTime(2023, 1, 1, 8, 0), DateTime(2023, 1, 1, 8, 30)), // 当天的时间段
        Period(DateTime(2023, 1, 1, 8, 45),
            DateTime(2023, 1, 1, 9, 25)), // 当天的另一个时间段
        Period(DateTime(2023, 1, 1, 10, 0),
            DateTime(2023, 1, 1, 10, 30)), // 非当天的时间段
        Period(DateTime(2023, 1, 2, 10, 0),
            DateTime(2023, 1, 2, 10, 30)) // 非当天的时间段
      ];

      // 假设分界线是上午9点（09:00）
      int boundaryHour = 9;

      // 当前时间是2023年1月1日上午10点（10:00）
      DateTime currentTime = DateTime(2023, 1, 1, 10, 0);

      // 计算指定日期的时间段交集
      var dateIntersects = periods.intersectByDay(currentTime, boundaryHour);

      // 预期结果应该包含两个Period
      expect(dateIntersects.length, 2);
      expect(dateIntersects[0].begin, DateTime(2023, 1, 1, 9, 0));
      expect(dateIntersects[0].end, DateTime(2023, 1, 1, 9, 25));
      expect(dateIntersects[1].begin, DateTime(2023, 1, 1, 10, 0));
      expect(dateIntersects[1].end, DateTime(2023, 1, 1, 10, 30));
    });
  });

  test("排序测试", () {
    /// 有一个是纯16日的，另一个横跨了16、17日
    final List<Period> testPeriods = [
      Period(DateTime(2024, 7, 16, 22, 15), DateTime(2024, 7, 16, 23, 46)),
      Period(DateTime(2024, 7, 15, 23, 58), DateTime(2024, 7, 17, 0, 15)),
    ];

    final Map<Date, List<Period>> sorted = testPeriods.groupByDate();

    expect(sorted[Date(2024, 7, 15)], hasLength(1));
    expect(sorted[Date(2024, 7, 16)], hasLength(2));
    expect(sorted[Date(2024, 7, 17)], hasLength(1));
  });
}
